#include "AlarmList.h"

void CurrentTime::updateTime()
{
#if UPDATE_TIME_WAY_BY_RTC == 1
    if (updateWay == eUpdateTime_Ticker)
    {
        updateTimeByTimeStamp();
    }
    else if (updateWay == eUpdateTime_RTC)
    {
        updateTimeByRTC();
    }
#else
    updateTimeByTimeStamp();
#endif
}

/**
 * @brief   通过时间戳更新时间
 * @param   ts: 不调形参时使用内部tickerTs作为时间戳,填形参时使用该形参作为时间戳
 * @return  None
 */
void CurrentTime::updateTimeByTimeStamp(time_t ts)
{
    time_t ts1;
    struct tm *currTm;

    if (ts != 0)
    {
        tickerTs = timeStamp = ts;
    }

    currTm = localtime(&tickerTs);
    year = currTm->tm_year + 1900;
    month = currTm->tm_mon + 1;
    date = currTm->tm_mday;
    day = (currTm->tm_wday > 0) ? currTm->tm_wday : 7;
    hour = currTm->tm_hour;
    minute = currTm->tm_min;
    second = currTm->tm_sec;

#if UPDATE_TIME_WAY_BY_RTC == 1
    rtcDs.setYear(year - 2000);
    rtcDs.setMonth(month);
    rtcDs.setDate(date);
    rtcDs.setDoW(day);
    rtcDs.setHour(hour);
    rtcDs.setMinute(minute);
    rtcDs.setSecond(second);
#endif  // #if UPDATE_TIME_WAY_BY_RTC == 1
}

void CurrentTime::updateTimeByRTC()
{
    RTClib RTC;
    DateTime now = RTC.now();

    year = now.year();
    month = now.month();
    date = now.day();
    day = rtcDs.getDoW();
    hour = now.hour();
    minute = now.minute();
    second = now.second();
    timeStamp = now.unixtime();
}

void CurrentTime::increaseTimeStamp()
{
    tickerTs++;
}

CurrentTime::CurrentTime()
{
    // updateWay = eUpdateTime_Ticker;
#if UPDATE_TIME_WAY_BY_RTC == 1
    updateWay = eUpdateTime_RTC;
#else
    updateWay = eUpdateTime_Ticker;
#endif  // #if UPDATE_TIME_WAY_BY_RTC == 1
    timeStamp = tickerTs = 1615109036;
    // CurrentTime(20, month, date, day, hour, minute, second);
}

CurrentTime::CurrentTime(time_t ts)
{
    updateTimeByTimeStamp(ts);
    // updateWay = eUpdateTime_Ticker;
#if UPDATE_TIME_WAY_BY_RTC == 1
    updateWay = eUpdateTime_RTC;
#else
    updateWay = eUpdateTime_Ticker;
#endif                          // #if UPDATE_TIME_WAY_BY_RTC == 1
    rtcDs.setClockMode(false);  // 24小时制
}

CurrentTime::CurrentTime(int16_t year, int8_t month, int8_t date, int8_t day, int8_t hour,
                         int8_t minute, int8_t second)
    : year(year), month(month), date(date), day(day), hour(hour), minute(minute), second(second)
{
#if UPDATE_TIME_WAY_BY_RTC == 1
    updateWay = eUpdateTime_RTC;
#else
    updateWay = eUpdateTime_Ticker;
#endif  // #if UPDATE_TIME_WAY_BY_RTC == 1

    rtcDs.setClockMode(false);  // 24小时制
}

CurrentTime::~CurrentTime() {}

AlarmType *AlarmList::compare(CurrentTime &current)
{
    AlarmType *p;
    size_t i;

    p = head;
    while (p != NULL)
    {
        if (p->date != 0)
        {
            if (p->date == current.date && p->hour == current.hour && p->minute == current.minute &&
                current.second == 1)
            {
                if (p->optIndex < OptIndex_Limit)
                {
                    OptFunTbl[p->optIndex].function(OptParam_Auto);
                }
            }
        }
        else
        {
            if (p->day == current.day && p->hour == current.hour && p->minute == current.minute &&
                current.second == 1)
            {
                if (p->optIndex < OptIndex_Limit)
                {
                    if (OptFunTbl[p->optIndex].function)
                    {
                        OptFunTbl[p->optIndex].function(OptParam_Auto);
                    }
                }
            }
        }
        p = p->next;
    }
    return p;
}

AlarmType *AlarmList::compare(AlarmType &current)
{
    AlarmType *p;
    size_t i;

    p = head;
    while (p != NULL)
    {
        if (compare(p, &current) == 0)
        {
            return p;
        }
        p = p->next;
    }
    return NULL;
}

/**
 * @brief   比较两个元素
 * @param   left: 比较的元素之一
 * @param   right: 比较的元素之一
 * @return  比较结果
 *  @arg  -1: left小于right;
 *  @arg  0: left等于right;
 *  @arg  1: left大于right;
 */
int AlarmList::compare(AlarmType *left, AlarmType *right)
{
    int retval = 1;
    if (left->day < right->day)
    {
        return -1;
    }
    else if (left->day == right->day)
    {
        if (left->hour < right->hour)
        {
            return -1;
        }
        else if (left->hour == right->hour)
        {
            if (left->minute < right->minute)
            {
                return -1;
            }
            else if (left->minute == right->minute)
            {
                if (left->optIndex < right->optIndex)
                {
                    return -1;
                }
                else if (left->optIndex == right->optIndex)
                {
                    return 0;
                }
                else
                {
                    return 1;
                }
            }
            else
            {
                return 1;
            }
        }
        else
        {
            return 1;
        }
    }
    else
    {
        return 1;
    }

    return retval;
}

/**
 * @brief   往链表中添加元素
 * @param   item: 要添加到链表的元素
 * @return  -2: 指针为空; -1: 存在一样的元素; 0: 一切正常
 */
int AlarmList::add(AlarmType *item)
{
    int val;
    AlarmType *p;
    if (item == NULL)
    {
        return -2;
    }
    if (len == 0)
    {
        item->next = NULL;
        item->pre = NULL;
        head = item;
        tail = item;
        len++;
    }
    else if (len == 1)
    {
        p = head;
        if ((val = compare(p, item)) < 0)
        {
            /* head-->|p|-->|item| */
            len++;
            item->next = p->next;
            item->pre = p;
            p->next = item;
            tail = item;
        }
        else
        {
            /* |item|-->|p| */
            len++;
            item->pre = p->pre;
            item->next = p;
            p->pre = item;
            head = item;
        }
    }
    else
    {
        p = head;
        while ((val = compare(p, item)) < 0)
        {
            if (p == tail)  // 链表中最后一个节点
            {
                break;
            }
            else  //
            {
                p = p->next;
            }
        }
        if (val == 0)
        {
            return -1;
        }
        else
        {
            if (p == head)
            {
                len++;
                item->next = p;
                item->pre = p->pre;
                p->pre = item;
                head = item;
            }
            else if (p == tail)  // 链表中最后一个元素
            {
                len++;
                if (compare(p, item) < 0)
                {
                    item->next = p->next;
                    item->pre = p;
                    p->next = item;
                    tail = item;
                }
                else
                {
                    p = p->pre;
                    item->next = p->next;
                    item->pre = p;
                    p->next = item;
                }
            }
            else  //
            {
                p = p->pre;
                len++;
                item->next = p->next;
                item->pre = p;
                p->next->pre = item;
                p->next = item;
            }
        }
    }
    return 0;
}

/**
 * @brief   往链表中添加元素
 * @param   date: 新闹钟的日期
 * @param   day: 新闹钟的星期
 * @param   hour: 新闹钟的小时数
 * @param   minute: 新闹钟的分钟数
 * @param   liveCnt: 新闹钟的倒计数
 * @param   optIndex: 新闹钟的闹铃事件
 * @return  -2: RAM中没有足够的空间; -1: 存在一样的元素; 0: 一切正常
 */
int AlarmList::add(int8_t date, int8_t day, int8_t hour, int8_t minute, int8_t liveCnt,
                   uint8_t optIndex)
{
    AlarmType *p;

    p = (AlarmType *)malloc(sizeof(AlarmType));
    if (p == NULL)
    {
        return -2;
    }

    p->date = date;
    p->day = day;
    p->hour = hour;
    p->minute = minute;
    p->optIndex = optIndex;
    p->cnt = liveCnt;
    p->next = NULL;
    p->pre = NULL;
    return add(p);
}

/**
 * @brief   删除元素
 * @param   ptr: 要删除的元素指针
 * @return  -1: 删除失败,指针为空; 0: 删除成功
 */
int AlarmList::remove(AlarmType *ptr)
{
    AlarmType *pNext, *pPre;
    size_t index = 0;

    if (ptr == NULL)
    {
        return -1;
    }
    else
    {
        pNext = ptr->next;
        pPre = ptr->pre;

        if (head == ptr)
        {
            head = pNext;
            len--;
            free(ptr);
        }
        else
        {
            pPre->next = pNext;
            pNext->pre = pPre;
            len--;
            free(ptr);
        }
    }
    return 0;
}

/**
 * @brief   删除与该元素属性相同的节点
 * @param   item: 要匹配的元素
 * @return  -1: 删除失败,指针为空; 0: 删除成功
 */
int AlarmList::remove(AlarmType &item)
{
    AlarmType *pNext, *pPre;
    AlarmType *p, *pfree;
    size_t index = 0, i;

    p = compare(item);
    if (p == NULL)
    {
        return -1;
    }
    else
    {
        remove(p);
    }

    return 0;
}

AlarmList::AlarmList(/* args */)
{
    head = tail = NULL;
    len = 0;
}

AlarmList::~AlarmList()
{
    AlarmType *p, *pfree;
    p = head;
    if (len > 0)
    {
        while (len > 0)
        {
            if (p == tail)
            {
                len = 0;
                break;
            }
            else
                len--;
            if (p == NULL)
            {
                break;
            }
            pfree = p;
            p = p->next;
            free(pfree);
        }
    }
}
